package cn.yitun.chat.yitunserverimapicore.business.contact.service.impl;

import cn.yitun.chat.yituncommonmessage.ExceptionEnum;
import cn.yitun.chat.yituncommonmessage.result.ResultMessage;
import cn.yitun.chat.yituncommonutil.YitunCollectionUtil;
import cn.yitun.chat.yituncommonutil.YitunStringUtil;
import cn.yitun.chat.yitunservercommonlib.converter.dto2vo.contact.ContactAddApplyDto2VoConverter;
import cn.yitun.chat.yitunservercommonlib.crud.yitun.CrudServiceImpl;
import cn.yitun.chat.yitunservercommonlib.dataentity.data.base.contact.ContactAddResult;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.contact.ContactAddApplyDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.contact.ContactAddVerifyAnswerDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.contact.ContactAddVerifyQuestionDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.userchat.ChatDataDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.po.contact.ContactAddVerifyQuestionInfo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.contact.ContactAddApplyVo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.contact.ContactAddVerifyQuestionVo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.contact.ContactHarassSettingVo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.contact.ContactRelationVo;
import cn.yitun.chat.yitunservercommonlib.enums.groupChat.GroupJoinVerifySettingTypeEnums;
import cn.yitun.chat.yitunservercommonlib.enums.userChat.UserRequestTypeEnums;
import cn.yitun.chat.yitunservercommonlib.util.NumUtil;
import cn.yitun.chat.yitunservercommonlib.util.R;
import cn.yitun.chat.yitunservercommonlib.util.codec.IdGen;
import cn.yitun.chat.yitunserverimapicore.business.contact.service.ContactAddService;
import cn.yitun.chat.yitunserverimbase.dao.contact.*;
import cn.yitun.chat.yitunserverimcore.general.main.biz.contact.manager.ContactCategoryManager;
import cn.yitun.chat.yitunserverimcore.general.main.biz.contact.manager.ContactHarassSettingManager;
import cn.yitun.chat.yitunserverimcore.general.main.biz.contact.manager.ContactRelationManager;
import cn.yitun.chat.yitunserverimcore.general.main.push.contact.ContactPush;
import cn.yitun.chat.yitunserverimcore.general.main.push.contact.ContactRelationPush;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * Date 2019-01-20 17:46:44<br>
 * Description 请问添加为联系人相关处理
 *
 * @author yitun<br>
 * @version 1.1
 */
@Service
@Transactional
public class ContactAddServiceImpl
		extends CrudServiceImpl<ContactAddVerifyQuestionDao, ContactAddVerifyQuestionDto, ContactAddVerifyQuestionInfo, ContactAddVerifyQuestionVo>
		implements ContactAddService {

	@Resource
	private ContactHarassSettingDao contactHarassSettingDAO;
	@Resource
	private ContactHarassSettingManager contactHarassSettingManager;
	@Resource
	private ContactRelationDao contactCategoryMemberDAO;
	@Resource
	private ContactAddApplyDao contactAddApplyDAO;
	@Resource
	private ContactAddVerifyAnswerDao contactAddVerifyAnswerDAO;
	@Resource
	private ContactRelationPush contactRelationPush;
	@Resource
	private ContactCategoryManager contactCategoryManager;
	@Resource
	private ContactRelationManager contactRelationManager;
	@Resource
	private ContactPush contactPush;

	/**
	 * 
	 * Date 2019-01-20 17:55:07<br>
	 * Description 获取用户被添加为联系人的验证设置
	 *
	 * @author yitun<br>
	 * @version 1.1
	 */
	public ResultMessage getContactAddVerifySetting(ChatDataDto query) {

		Long targetUserId = query.getTargetUserId();
		Long applyUserId = query.getApplyUserId();

		ResultMessage rm = new ResultMessage();

		boolean isBlocked = contactRelationManager.isBlocked(targetUserId, applyUserId);
		if (isBlocked) {
			rm.addWarning(ExceptionEnum.SOCK_CONTACT_APPLY_REQUEST_REFUSE);
			return rm;
		}

		List<ContactAddVerifyQuestionVo> questionList = null;
		ContactHarassSettingVo setting = contactHarassSettingDAO.getVOByUserId(targetUserId);

		if (setting == null) {
			setting = new ContactHarassSettingVo();
			setting.setUserId(targetUserId);
			setting.setVerifyType(GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_AUTH.getType());
		}

		String type = setting.getVerifyType();
		// 防骚扰设置为回答问题并亲自验证时，获取设置的问题列表
		if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_CONFIRM.getType().equals(type)) {
			questionList = dao.listVO(R.param("targetUserId", targetUserId));
		}

		if (null == questionList) {
			questionList = new ArrayList<>();
		}

		rm.bodyPut("verifySetting", setting);
		rm.bodyPut("questionList", questionList);
		return rm;
	}

	/**
	 * 
	 * Date 2019-01-20 17:58:09<br>
	 * Description 处理添加为好友的请求
	 * 
	 * @param currentUserId
	 * @param apply
	 * @author yitun<br>
	 * @version 1.1
	 */
	public ResultMessage userAddApply(Long currentUserId, ContactAddApplyDto apply) {
		ResultMessage rm = new ResultMessage();
		apply.setCurrentUserId(currentUserId);
		List<ContactAddVerifyAnswerDto> answerList = apply.getAnswerList();
		Long applyUserId = apply.getApplyUserId();
		Long applyCategoryId = apply.getCategoryId();
		String applyRemark = apply.getRemark();

		Long targetUserId = apply.getTargetUserId();

		String applyAnswer = apply.getAnswer();

		// 先判断是否在对方黑名单中
		boolean isBlocked = contactRelationManager.isBlocked(targetUserId, applyUserId);
		if (isBlocked) {
			rm.addWarning(ExceptionEnum.SOCK_CONTACT_APPLY_REQUEST_REFUSE);
			return rm;
		}

		ContactRelationVo cr = contactCategoryMemberDAO.getVOByContactUserId(applyUserId, targetUserId);
		if (null != cr) {
			rm.addWarning(ExceptionEnum.SOCK_CONTACT_APPLY_REQUEST_HAS_ADD);
			return rm;
		}

		List<ContactAddApplyVo> list = contactAddApplyDAO.listVO(R.param("applyUserId", applyUserId).put("targetUserId", targetUserId));
		if (YitunCollectionUtil.isNotEmpty(list)) {
			for (ContactAddApplyVo a : list) {
				if (UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType().equals(a.getHandleType())) {
					rm.addPrompt(ExceptionEnum.SOCK_CONTACT_APPLY_REQUEST_HAS_SEND);
					return rm;
				}
			}
		}

		// 先获取对方的安全设置
		ContactHarassSettingVo setting = contactHarassSettingManager.getByUserId(targetUserId);

		String verifyType = setting.getVerifyType();
		String settingAnswer = YitunStringUtil.isEmpty(setting.getAnswer()) ? "" : setting.getAnswer();

		String handleType = UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType();

		if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_ANY.getType().equals(verifyType)) {
			// 如果对方允许任何人添加为好友，那么直接将2人互相添加为好友
			Long targetCategoryId = contactCategoryManager.getOrCreateDefaultCategoryId(targetUserId);
			String targetRemark = "";

			handleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();
			ContactAddApplyDto addApply = addContactAddApply(handleType, apply, answerList, setting);

			bothContact(currentUserId, applyUserId, applyCategoryId, applyRemark, targetUserId, targetCategoryId, targetRemark);
			handleUserAddResponse(IdGen.getNumber(), addApply, "");

		} else if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_ANSWER.getType().equals(verifyType)) {
			// 如果是回答问题，那么回答正确后直接将2人互相添加为好友
			if (YitunStringUtil.isEmpty(applyAnswer)) {
				rm.addWarning(ExceptionEnum.SOCK_CONTACT_CATEGORY_NEED_ANSWER);
				return rm;
			}

			String ra = applyAnswer.toLowerCase().trim();
			String sa = settingAnswer.toLowerCase().trim();

			if (!ra.equals(sa)) {
				rm.addWarning(ExceptionEnum.SOCK_CONTACT_CATEGORY_WRONG_ANSWER);
				return rm;
			}

			handleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();
			ContactAddApplyDto addApply = addContactAddApply(handleType, apply, answerList, setting);

			Long targetCategoryId = contactCategoryManager.getOrCreateDefaultCategoryId(targetUserId);
			String targetRemark = "";
			bothContact(currentUserId, applyUserId, applyCategoryId, applyRemark, targetUserId, targetCategoryId, targetRemark);
			handleUserAddResponse(IdGen.getNumber(), addApply, "");

		} else if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_AUTH.getType().equals(verifyType)) {
			// 如果需要验证，那么将请求信息保存，待用户自己验证
			ContactAddApplyDto addApply = addContactAddApply(handleType, apply, answerList, setting);

			Long applyId = addApply.getId();// 请求记录id

			// 推送添加请信息
			contactPush.pushAddApply(currentUserId, applyId, targetUserId);

		} else if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_CONFIRM.getType().equals(verifyType)) {
			ContactAddApplyDto addApply = addContactAddApply(handleType, apply, answerList, setting);

			Long applyId = addApply.getId();// 请求记录id
			// 推送添加请信息
			contactPush.pushAddApply(currentUserId, applyId, targetUserId);
		}
		return rm;
	}

	/**
	 * 相互关注
	 * @param key
	 * @param applyUserId
	 * @param requestCategoryId
	 * @param requestRemark
	 * @param targetUserId
	 * @param addCategoryId
	 * @param addRemark
	 * @return
	 */
	private boolean bothContact(
			Long key,
			Long applyUserId,
			Long requestCategoryId,
			String requestRemark,
			Long targetUserId,
			Long addCategoryId,
			String addRemark) {

		boolean mark = true;

		key = IdGen.getNumber();
		contactRelationManager.bothContact(applyUserId, requestCategoryId, requestRemark, targetUserId, addCategoryId, addRemark);
		// 推送添加成功消
//		ContactRelationDto applyMember = new ContactRelationDto();
//		applyMember.setOwnerUserId(applyUserId);
//		applyMember.setContactUserId(targetUserId);
//		applyMember.setRemark(requestRemark);
//		applyMember.setCategoryId(requestCategoryId);
		contactRelationPush.pushAdd(key, targetUserId, applyUserId);

//		ContactRelationDto addMember = new ContactRelationDto();
//		addMember.setOwnerUserId(targetUserId);
//		addMember.setContactUserId(applyUserId);
//		addMember.setRemark(addRemark);
//		addMember.setCategoryId(addCategoryId);
		contactRelationPush.pushAdd(key, applyUserId, targetUserId);
		return mark;
	}

	private ContactAddApplyDto addContactAddApply(String handleType, ContactAddApplyDto request, List<ContactAddVerifyAnswerDto> answerList, ContactHarassSettingVo setting) {

		Long applyUserId = request.getApplyUserId();
		Long applyCategoryId = request.getCategoryId();
		String applyRemark = request.getRemark();

		Long targetUserId = request.getTargetUserId();
		String applyAnswer = request.getAnswer();

		String applyMessage = request.getMessage();

		String verifyType = setting.getVerifyType();
		// String settingAnswer = setting.getAnswer();

		ContactAddApplyDto apply = new ContactAddApplyDto();
		apply.setApplyUserId(applyUserId);
		apply.setTargetUserId(targetUserId);
		apply.setCategoryId(applyCategoryId);
		apply.setRemark(applyRemark);
		apply.setVerifyType(verifyType);
		apply.setQuestion(setting.getQuestion());
		apply.setAnswer(applyAnswer);
		apply.setHandleType(handleType);
		// apply.setHandleDateTime(LocalDateTime.now());
		apply.setMessage(applyMessage);
		apply.setCreateBy(request.getCurrentUserId());
		apply.setUpdateBy(request.getCurrentUserId());
		contactAddApplyDAO.save(apply);

		if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_CONFIRM.getType().equals(verifyType)
				&& null != answerList && !answerList.isEmpty()) {
			Map<Long, ContactAddVerifyQuestionVo> questionMap = new HashMap<>();
			List<ContactAddVerifyQuestionVo> questionList = dao.listVO(
					R.param("targetUserId", targetUserId));
			if (null != questionList && !questionList.isEmpty()) {
				for (ContactAddVerifyQuestionVo q : questionList) {
					questionMap.put(q.getId(), q);
				}
			}
			Long applyId = apply.getId();// 请求消息的id(对应UserAddRequest中的id)

			List<ContactAddVerifyAnswerDto> list = new ArrayList<>();
			for (ContactAddVerifyAnswerDto a : answerList) {

				Long questionId = a.getQuestionId();// 问题id(对应UserAddVerifyQuestion中的id)
				String question = "";// 问题
				String answer = a.getAnswer();// 答案
				ContactAddVerifyQuestionVo q = questionMap.get(questionId);
				if (null != q) {
					question = q.getQuestion();
				}
				ContactAddVerifyAnswerDto bean = new ContactAddVerifyAnswerDto();
				bean.setApplyId(applyId);
				bean.setApplyUserId(applyUserId);
				bean.setTargetUserId(targetUserId);
				bean.setQuestionId(questionId);
				bean.setQuestion(question);
				bean.setAnswer(answer);
				bean.setCreateBy(apply.getCurrentUserId());
				bean.setUpdateBy(apply.getCurrentUserId());
				list.add(bean);
			}

			if (!list.isEmpty()) {
				contactAddVerifyAnswerDAO.saveList(list);
			}
		}
		return apply;
	}

	public ResultMessage userAddResponse(Long key, ContactAddApplyDto response) {

		ResultMessage rm = new ResultMessage();

		List<Long> applyIds = response.getApplyIds();// 请求记录id
		// String applyUserId = response.getApplyUserId();// 添加联系人的请求用户
		// String targetUserId = response.getTargetUserId();// 被添加的用户
		Long targetCategoryId = response.getCategoryId();// 分组id
		String targetRemark = response.getRemark();// 备注

		String handleType = response.getHandleType();// 处理结果：0：未处、 1：同意、2：拒绝、3：忽略
		String message = response.getMessage();// 附加消息

		if (YitunCollectionUtil.isNotEmpty(applyIds)) {
			for (Long applyId : applyIds) {
				ContactAddApplyVo apply = contactAddApplyDAO.getVO(applyId);
				if (null != apply) {

					Long applyUserId = apply.getApplyUserId();// 添加联系人的请求用户
					Long targetUserId = apply.getTargetUserId();// 被添加的用户

					apply.setHandleType(handleType);
					contactAddApplyDAO.update(ContactAddApplyDto2VoConverter.INSTANCE.vo2dto(apply));

					if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(handleType)) {
						Long requestCategoryId = apply.getCategoryId();
						String requestRemark = apply.getRemark();
						if (NumUtil.isInValid(targetCategoryId))
							targetCategoryId = contactCategoryManager.getOrCreateDefaultCategoryId(targetUserId);


						ContactRelationVo cr = contactCategoryMemberDAO.getVOByContactUserId(applyUserId, targetUserId);
						if (null == cr)
							bothContact(key, applyUserId, requestCategoryId, requestRemark, targetUserId, targetCategoryId, targetRemark);

					}
					handleUserAddResponse(key, ContactAddApplyDto2VoConverter.INSTANCE.vo2dto(apply), message);
				}
			}
		}
		return rm;
	}

	/**
	 * 
	 * Date 2019-01-20 17:53:38<br>
	 * Description 推送被添加为好友的响应消息
	 * 
	 * @param key
	 * @param userAddRequest
	 * @param message
	 * @author yitun<br>
	 * @version 1.1
	 */
	private void handleUserAddResponse(Long key, ContactAddApplyDto userAddRequest, String message) {
		String handleType = userAddRequest.getHandleType();
		Long applyId = userAddRequest.getId();// 请求记录id
		Long applyUserId = userAddRequest.getApplyUserId();// 添加联系人的请求用户
		Long targetUserId = userAddRequest.getTargetUserId();// 被添加的用户
		ContactAddResult result = new ContactAddResult();

		result.setApplyId(applyId);
		result.setApplyUserId(applyUserId);
		result.setTargetUserId(targetUserId);
		result.setMessage(message);
		result.setHandleType(handleType);
		contactPush.pushApplyHandle(key, result, applyUserId);
	}
}
